package com.bugsnag.ohos;

import com.bugsnag.ohos.internal.ImmutableConfig;

import java.util.HashSet;
import java.util.Set;

/**
 * PluginClient
 *
 * @since 2021-07-02
 */
public class PluginClient {
    private static final String NDK_PLUGIN = "com.bugsnag.ohos.NdkPlugin";
    private static final String ANR_PLUGIN = "com.bugsnag.ohos.AnrPlugin";
    private static final String RN_PLUGIN = "com.bugsnag.ohos.BugsnagReactNativePlugin";
    Set<Plugin> plugins;
    private ImmutableConfig immutableConfig;
    private Logger logger;
    private Plugin ndkPlugin;
    private Plugin anrPlugin;
    private Plugin rnPlugin;

    /**
     * constructor
     *
     * @param userPlugins
     * @param immutableConfig
     * @param logger
     */
    public PluginClient(Set<Plugin> userPlugins, ImmutableConfig immutableConfig, Logger logger) {
        this.immutableConfig = immutableConfig;
        this.logger = logger;
        Set<Plugin> set = new HashSet<>();
        set.addAll(userPlugins);
        ndkPlugin = instantiatePlugin(NDK_PLUGIN);
        anrPlugin = instantiatePlugin(ANR_PLUGIN);
      //  rnPlugin = instantiatePlugin(RN_PLUGIN);

        if (ndkPlugin != null) {
            set.add(ndkPlugin);
        }
        if (anrPlugin != null) {
            set.add(anrPlugin);
        }
        if (rnPlugin != null) {
            set.add(rnPlugin);
        }
        plugins = set;
    }

    private Plugin instantiatePlugin(String clz) {
        try {
            Class pluginClz = Class.forName(clz);
            return (Plugin) pluginClz.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException exc) {
            logger.d("Plugin " + clz + " is not on the classpath - functionality will not be enabled.");
            return null;
        }
    }

    /**
     * load plugins
     *
     * @param client
     */
    public void loadPlugins(Client client) {
        for (Plugin plugin : plugins) {
            loadPluginInternal(plugin, client);
        }
    }

    /**
     * set auto notify
     *
     * @param client
     * @param autoNotify
     */
    public void setAutoNotify(Client client, boolean autoNotify) {
        setAutoDetectAnrs(client, autoNotify);

        if (autoNotify) {
            if (ndkPlugin != null) {
                ndkPlugin.load(client);
            }
        } else {
            if (ndkPlugin != null) {
                ndkPlugin.unload();
            }
        }
    }

    /**
     * set auto detect anrs
     *
     * @param client
     * @param autoDetectAnrs
     */
    public void setAutoDetectAnrs(Client client, boolean autoDetectAnrs) {
        if (autoDetectAnrs) {
            if (anrPlugin != null) {
                anrPlugin.load(client);
            }
        } else {
            if (anrPlugin != null) {
                anrPlugin.unload();
            }
        }
    }

    /**
     * find plugin by clazz
     *
     * @param clz
     * @return Plugin
     */
    public Plugin findPlugin(Class clz) {
        for (Plugin plugin : plugins) {
            if (plugin.getClass() == clz) {
                return plugin;
            }
        }
        return null;
    }

    private void loadPluginInternal(Plugin plugin, Client client) {
        String name = plugin.getClass().getName();
        ErrorTypes errorTypes = immutableConfig.getEnabledErrorTypes();

        // only initialize NDK/ANR plugins if automatic detection enabled
        if (name == NDK_PLUGIN) {
            if (errorTypes.ndkCrashes) {
                plugin.load(client);
            }
        } else if (name == ANR_PLUGIN) {
            if (errorTypes.anrs) {
                plugin.load(client);
            }
        } else {
            plugin.load(client);
        }
    }
}
